package com.simen.hellobytes;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.URL;
import java.util.List;
import java.util.logging.Logger;
import java.util.regex.Pattern;

import com.simen.hellobytes.platform.Platform;

import java.io.File;

/**
 * @author Created by Simen.
 * @date 创建日期 2018/5/27 12:43
 * @modify 修改者 Simen
 */
public class SystemUtil {

    public static Platform getSystemType() {
        String os = System.getProperty("os.name");
        String dalvik = System.getProperty("java.vm.name");

        if ("Dalvik".equals(dalvik)) {
            //todo whether check android.os.Build.VERSION.SDK_INT
            return Platform.ANDROID;
        } else if (StringUtil.isEmpty(os)) {
            return Platform.UNKNOWN;
        } else if (os.toLowerCase().startsWith("win")) {
            return Platform.WINDOWS;
        } else if (os.toLowerCase().startsWith("mac")) {
            return Platform.OSX;
        } else if (os.toLowerCase().startsWith("linux")) {
            return Platform.LINUX;
        }

        return Platform.UNKNOWN;
    }

    private static String filePathSeparator = null;
    private static String lineSeparator = null;

    /**
     * @return 返回文件路径分隔符
     */
    public static String getFilePathSeparator() {
        if (filePathSeparator == null) {
            filePathSeparator = File.separator;
        }

        return filePathSeparator;
    }

    /**
     * @return 返回标准换行符
     */
    public static String getLineSeparator() {
        if (lineSeparator == null) {
            lineSeparator = System.getProperty("line.separator", File.separator);
        }

        return lineSeparator;
    }

    /**
     * @return 返回用户名
     */
    public static String getUserName() {
        return System.getProperty("user.name");
    }

    /**
     * @return 返回用户主目录
     */
    public static String getUserHome() {
        return System.getProperty("user.home");
    }

    /**
     * @return 返回当前工作目录
     */
    public static String getUserDir() {
        return System.getProperty("user.dir");
    }

    private static volatile String pid;
    private static volatile String parentPid;
    private static volatile String parentProcessName;

    enum ProcessAttr {
        PROCESS_ID("ProcessId"),
        PARENT_PROCESS_ID("ParentProcessId"),
        NAME("Name"),
        OS_NAME("OSName"),
        STATUS("Status"),
        THREAD_COUNT("ThreadCount"),
        WINDOWS_VERSION("WindowsVersion"),
        SESSION_ID("SessionId");

        final String value;

        ProcessAttr(String value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return value;
        }
    }

    /**
     * Get current process ID
     *
     * @return
     */
    public static String getPID() {
        if (pid == null) {
            synchronized (SystemUtil.class) {
                if (pid == null) {
                    RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
                    String processName = runtimeMXBean.getName();
                    if (processName.indexOf('@') != -1) {
                        pid = processName.substring(0, processName.indexOf('@'));
                    } else {
                        pid = null;
                    }
                }
            }
        }
        return pid;
    }

    /**
     * Get parent process id
     *
     * @param pid
     * @return
     */
    private static String getParentPID(String pid) {
        if (parentPid == null) {
            synchronized (SystemUtil.class) {
                if (parentPid == null) {
                    parentPid = getProcessAttr(pid, ProcessAttr.PARENT_PROCESS_ID);
                }
            }
        }
        return parentPid;
    }

    /**
     * Get process information
     *
     * @return
     */
    public static String getProcessAttr(String pid, ProcessAttr attrKey) {
        String result = null;
        if (pid == null || attrKey == null) {
            return null;
        }

        BufferedReader br = null;
        try {
            String cmd = "wmic process where ProcessId=" + pid + " get " + attrKey;
            br = new BufferedReader(
                    new InputStreamReader(
                            Runtime.getRuntime().exec(cmd).getInputStream()));
            String line;
            while ((line = br.readLine()) != null) {
                line = line.trim();
                if (line.length() > 0) {
                    result = line;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }


    /**
     * Determine if the application is opened with window explorer
     *
     * @return
     */
    public static boolean isStartWithWindowExplorer() {
        return isStartWithContain("explorer.exe");
    }

    /**
     * Determine if it is running in the specified process
     *
     * @param pidNameRegex
     * @return
     */
    public static boolean isStartWithContain(String... pidNameRegex) {
        String parentProcessName = getParentProcessName(getPID());
        if (parentProcessName == null || parentProcessName.isEmpty()) {
            return false;
        }
        for (String name : pidNameRegex) {
            Pattern pattern = Pattern.compile(name);
            if (pattern.matcher(parentProcessName).matches()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Get parent process name
     *
     * @param pid
     * @return
     */
    private static String getParentProcessName(String pid) {
        if (parentProcessName == null) {
            synchronized (SystemUtil.class) {
                if (parentProcessName == null) {
                    parentProcessName = getProcessAttr(getParentPID(pid), ProcessAttr.NAME);
                }
            }
        }
        return parentProcessName;
    }

    /**
     * Determine whether it is currently in debug mode
     *
     * @return
     */
    public static boolean isDebug() {
        List<String> args = ManagementFactory.getRuntimeMXBean().getInputArguments();
        for (String arg : args) {
            if (arg.startsWith("-Xrunjdwp") || arg.startsWith("-agentlib:jdwp")) {
                return true;
            }
        }
        return false;
    }

    public static boolean isRunInJar(Class cls){
        URL url = cls.getResource("");
        String protocol = url.getProtocol();
        if("jar".equals(protocol)){
            // jar 中
            return true;
        }else if("file".equals(protocol)){
            // 非jar 中 （文件class 中）
        }

        return false;
    }

    public static void main(String[] args) {
        System.out.println(getPID());
        System.out.println(isStartWithContain("idea\\d+.exe"));
        System.out.println(isDebug());
        System.out.println(isRunInJar(SystemUtil.class));
    }


}
